package dbinfo

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

// 虚拟实体
type VirtualEntity struct {
	EnableTag              int            `json:"enableTag"`              //控制操作值集合
	CheckRepeatCombination []string       `json:"checkRepeatCombination"` //检查待新增内容是否存在重复数据(多字段组合重复即重复)集合
	CheckRepeatAlone       map[string]int `json:"checkRepeatAlone"`       //检查待新增内容是否存在重复数据(单独字段重复即重复)集合

	JsonDbName      string `json:"jsonDbName"`      // 数据库名称别名,对应数据库全局配置名
	JsonName        string `json:"jsonName"`        // 所在数据库表对象名(首字母小写)
	DbName          string `json:"dbName"`          // 所在数据库名称
	TableFullName   string `json:"tableFullName"`   // 所在数据库表表全名(数据库.表名)
	TableName       string `json:"tableName"`       // 所在数据库表表名称
	TableObj        string `json:"tableObj"`        // 所在数据库表对象名(首字母大写)
	KeyName         string `json:"keyName"`         // 表主键名称(首字母大写)
	KeyJson         string `json:"keyJson"`         // 表主键名称(json名称)
	KeyField        string `json:"keyField"`        // 表主键字段
	KeyFields       string `json:"keyFields"`       // 表主键字段集合(如果有多个主键,则全取,并以','分隔)
	KeyLen          int    `json:"keyLen"`          // 主键长度
	AutoKey         bool   `json:"autoKey"`         // 是否自增主键
	HasPid          bool   `json:"hasPid"`          // 是否存在pid
	HasPath         bool   `json:"hasPath"`         // 是否存在path
	HasRecordKey    bool   `json:"hasRecordKey"`    // 是否存在recordKey
	HasMemo         bool   `json:"hasMemo"`         // 是否存在memo
	HasCreator      bool   `json:"hasCreator"`      // 是否存在creator
	HasCreateDate   bool   `json:"hasCreateDate"`   // 是否存在createDate
	HasModifieder   bool   `json:"hasModifieder"`   // 是否存在modifieder
	HasModifiedDate bool   `json:"hasModifiedDate"` // 是否存在modifiedDate
	HasState        bool   `json:"hasState"`        // 是否存在state
	HasRank         bool   `json:"hasRank"`         // 是否存在rank
	HasEdition      bool   `json:"hasEdition"`      // 是否存在edition
	HasPassword     bool   `json:"hasPassword"`     // 是否存在password
	HasSign         bool   `json:"hasSign"`         // 是否存在sign
	HasOnlyign      bool   `json:"hasOnlyign"`      // 是否存在onlyign
	HasDelSign      bool   `json:"hasDelSign"`      // 是否存在delSign
	HasAttached     bool   `json:"hasAttached"`     // 是否存在attached
	BigTextFields   string `json:"bigTextFields"`   // 大文本字段名称集合,';'分隔

	Fields    map[string]*FieldInfo `json:"fields"`    // 字段信息,以字段名小驼峰形式做键
	RelFields map[string]*FieldInfo `json:"relFields"` // 关联字段信息,以字段名小驼峰形式做键
}

/**
 * 创建虚拟实体
 * @param jsonDbName 数据库名称别名,对应数据库全局配置名
 * @param jsonName 数据库表对象名(首字母小写)
 * @return *VirtualEntity 返回虚拟实体
 * @return
 */
func CreateVirtualEntity(jsonDbName, jsonName string) *VirtualEntity {
	// 读取json配置文件信息到实体中
	file, err := os.Open("./config/project/" + jsonDbName + "/entity/" + jsonName + ".json")
	if err != nil {
		return nil
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	result := &VirtualEntity{}
	err = decoder.Decode(result)
	if err != nil {
		return nil
	}

	return result
}

// 创建虚拟实体
func (VirtualEntity) New() *VirtualEntity {
	result := VirtualEntity{}

	result.JsonDbName = ""         // 数据库名称别名,对应数据库全局配置名
	result.JsonName = ""           // 所在数据库表对象名(首字母小写)
	result.DbName = ""             // 所在数据库名称
	result.TableFullName = ""      // 所在数据库表表全名(数据库.表名)
	result.TableName = ""          // 所在数据库表表名称
	result.TableObj = ""           // 所在数据库表对象名(首字母大写)
	result.KeyName = ""            // 表主键名称(首字母大写)
	result.KeyJson = ""            // 表主键名称(json名称)
	result.KeyField = ""           // 表主键字段
	result.KeyFields = ""          // 表主键字段集合(如果有多个主键,则全取,并以','分隔)
	result.KeyLen = 0              // 主键长度
	result.AutoKey = false         // 是否自增主键
	result.HasPid = false          // 是否存在pid
	result.HasPath = false         // 是否存在path
	result.HasRecordKey = false    // 是否存在recordKey
	result.HasMemo = false         // 是否存在memo
	result.HasCreator = false      // 是否存在creator
	result.HasCreateDate = false   // 是否存在createDate
	result.HasModifieder = false   // 是否存在modifieder
	result.HasModifiedDate = false // 是否存在modifiedDate
	result.HasState = false        // 是否存在state
	result.HasRank = false         // 是否存在rank
	result.HasEdition = false      // 是否存在edition
	result.HasPassword = false     // 是否存在password
	result.HasSign = false         // 是否存在sign
	result.HasOnlyign = false      // 是否存在onlyign
	result.HasDelSign = false      // 是否存在delSign
	result.HasAttached = false     // 是否存在attached
	result.BigTextFields = ""      // 大文本字段名称集合,';'分隔

	result.Fields = map[string]*FieldInfo{}    // 字段信息,以字段名小驼峰形式做键
	result.RelFields = map[string]*FieldInfo{} // 字段信息,以字段名小驼峰形式做键

	return &result
}

/**
 * 取主键值
 * @return
 */
func (entity *VirtualEntity) GetKeyValue() interface{} {
	if len(entity.Fields) < 1 {
		return nil
	}

	if field, ok := entity.Fields[entity.KeyJson]; ok {
		return field.Value
	}

	return nil
}

/**
 * 设置主键值
 * @param value
 * @return
 */
func (entity *VirtualEntity) SetKeyValue(val interface{}) *VirtualEntity {
	if len(entity.Fields) < 1 {
		return nil
	}

	if field, ok := entity.Fields[entity.KeyJson]; ok {
		field.Value = val
		return entity
	}

	return entity
}

/**
 * 取指定字段值
 * @param name
 * @return
 */
func (entity *VirtualEntity) GetValue(name string) interface{} {
	if strings.TrimSpace(name) == "" {
		return nil
	}

	if len(entity.Fields) < 1 {
		return nil
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.Fields {
		if field.Field == name { // 直接按字段名找
			return field.Value
		}

		if field.JsonName == name { // 按小驼峰名找
			return field.Value
		}

		if field.Name == name { // 按大驼峰名找
			return field.Value
		}
	}

	return nil
}

/**
 * 设置指定字段值
 * @param name
 * @param value
 * @return
 */
func (entity *VirtualEntity) SetValue(name string, value interface{}) bool {
	if strings.TrimSpace(name) == "" {
		return false
	}

	if len(entity.Fields) < 1 {
		return false
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.Fields {
		if field.Field == name { // 直接按字段名找
			field.Value = value
			return true
		}

		if field.JsonName == name { // 按小驼峰名找
			field.Value = value
			return true
		}

		if field.Name == name { // 按大驼峰名找
			field.Value = value
			return true
		}
	}

	return false
}

/**
 * 取指定关联字段值
 * @param name
 * @return
 */
func (entity *VirtualEntity) GetRelValue(name string) interface{} {
	if strings.TrimSpace(name) == "" {
		return nil
	}

	if len(entity.RelFields) < 1 {
		return nil
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.RelFields {
		if field.Field == name { // 直接按字段名找
			return field.Value
		}

		if field.JsonName == name { // 按小驼峰名找
			return field
		}

		if field.Name == name { // 按大驼峰名找
			return field.Value
		}
	}

	return nil
}

/**
 * 设置指定关联字段值
 * @param name
 * @param value
 * @return
 */
func (entity *VirtualEntity) SetRelValue(name string, value interface{}) bool {
	if strings.TrimSpace(name) == "" {
		return false
	}

	if len(entity.RelFields) < 1 {
		return false
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.RelFields {
		if field.Field == name { // 直接按字段名找
			field.Value = value
			return true
		}

		if field.JsonName == name { // 按小驼峰名找
			field.Value = value
			return true
		}

		if field.Name == name { // 按大驼峰名找
			field.Value = value
			return true
		}
	}

	return false
}

/**
 * 对象值数据转map
 * @return
 */
func (entity *VirtualEntity) ToMap() map[string]interface{} {
	if len(entity.Fields) < 1 {
		return map[string]interface{}{}
	}

	result := make(map[string]interface{}, len(entity.Fields))
	for _, field := range entity.Fields {
		result[field.JsonName] = field.Value
	}

	return result
}

/**
 * map赋值对象字段
 * @param map
 * @return
 */
func (entity *VirtualEntity) FormMap(data map[string]interface{}) *VirtualEntity {
	if len(entity.Fields) < 1 {
		return entity
	}

	for key, value := range data {
		if field, ok := entity.Fields[key]; ok {
			field.Value = value
			continue
		}
	}

	return entity
}

/**
 * 取字段信息
 * @param map
 * @return
 */
func (entity *VirtualEntity) GetField(name string) *FieldInfo {
	if strings.TrimSpace(name) == "" {
		return nil
	}

	if len(entity.Fields) < 1 {
		return nil
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.Fields {
		if field.Field == name { // 直接按字段名找
			return field
		}

		if field.JsonName == name { // 按小驼峰名找
			return field
		}

		if field.Name == name { // 按大驼峰名找
			return field
		}
	}

	return nil
}

/**
 * 取关联字段信息
 * @param map
 * @return
 */
func (entity *VirtualEntity) GetRelField(name string) *FieldInfo {
	if strings.TrimSpace(name) == "" {
		return nil
	}

	if len(entity.RelFields) < 1 {
		return nil
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.RelFields {
		if field.Field == name { // 直接按字段名找
			return field
		}

		if field.JsonName == name { // 按小驼峰名找
			return field
		}

		if field.Name == name { // 按大驼峰名找
			return field
		}
	}

	return nil
}

/**
 * 取字段名称
 * @param map
 * @return
 */
func (entity *VirtualEntity) GetFieldName(name string) string {
	if strings.TrimSpace(name) == "" {
		return ""
	}

	if len(entity.Fields) < 1 {
		return ""
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.Fields {
		if field.Field == name { // 直接按字段名找
			return field.Field
		}

		if field.Name == name { // 按大驼峰名找
			return field.Field
		}

		if field.JsonName == name { // 按小驼峰名找
			return field.Field
		}
	}

	return ""
}

/**
 * 判断是否存在指定名称的字段
 * @param name
 * @return
 */
func (entity *VirtualEntity) HasFieldName(name string) bool {
	if strings.TrimSpace(name) == "" {
		return false
	}

	if len(entity.Fields) < 1 {
		return false
	}

	name = strings.TrimSpace(name)

	for _, field := range entity.Fields {
		if field.JsonName == name { // 按小驼峰名找
			return true
		}

		if field.Field == name { // 直接按字段名找
			return true
		}

		if field.Name == name { // 按大驼峰名找
			return true
		}
	}

	name = strings.ToLower(name)

	// 按字段名找
	for _, field := range entity.Fields {
		if field.Field == name {
			return true
		}
	}

	return false
}

func (entity *VirtualEntity) GetKeyField() *FieldInfo {
	if field, ok := entity.Fields[entity.KeyJson]; ok {
		return field
	}

	return nil
}

/**
 * 创建当前'记录验证串'
 * @param key 加密密钥
 * @return String 子节点集合
 */
func (entity *VirtualEntity) CreateRecordKey(key string) string {
	if len(entity.Fields) < 1 {
		return ""
	}

	temp := ""
	for _, field := range entity.Fields {
		if strings.Contains(RecordKeyIgnoreField[0], "/"+field.Field+"/") {
			continue
		}

		if field.Value == nil {
			temp = temp + ";"
			continue
		}

		switch reflect.TypeOf(field.Value).String() {
		case "time.Time":
			temp = temp + field.Value.(time.Time).Format(timeFormat) + ";"
		case "float32", "float64":
			temp = temp + fmt.Sprintf("%.3f", field.Value) + ";"
		case "decimal.Decimal":
			//temp = temp + field.Value.(decimal.Decimal).StringFixed(3) + ";"//decimal中的方法
			m := fmt.Sprintf("%v", field.Value)
			f, err := strconv.ParseFloat(m, 64)
			if err != nil {
				temp = temp + "0.000;"
			} else {
				temp = temp + fmt.Sprintf("%.3f", f) + ";"
			}
		default:
			temp = temp + fmt.Sprintf("%v", field.Value) + ";"
		}
	}

	data := []byte(temp)
	md5Ctx := md5.New()
	md5Ctx.Write(data)
	cipherStr := md5Ctx.Sum(nil)
	result := hex.EncodeToString(cipherStr)

	return strings.ToUpper(result)
}

/*
 * 根据结构体创建map的记录验证值
 * @param data 数据
 * @return
 */
func (entity *VirtualEntity) CreateRecordKeyByMap(data map[string]interface{}) string {
	temp := ""
	for k := range entity.Fields { //只有数组才能固定顺序
		if k == TableRecordKey[1] { //recordKey字段不能参与,并且一旦轮询到recordKey就结束
			break
		}

		v, ok := data[k]
		if !ok {
			temp = temp + ";"
			continue
		}

		if v == nil {
			temp = temp + ";"
			continue
		}

		switch reflect.TypeOf(v).String() {
		case "time.Time":
			temp = temp + v.(time.Time).Format(timeFormat) + ";"
		case "float32", "float64":
			temp = temp + fmt.Sprintf("%.3f", v) + ";"
		case "decimal.Decimal":
			//temp = temp + field.Value.(decimal.Decimal).StringFixed(3) + ";"//decimal中的方法
			m := fmt.Sprintf("%v", v)
			f, err := strconv.ParseFloat(m, 64)
			if err != nil {
				temp = temp + "0.000;"
			} else {
				temp = temp + fmt.Sprintf("%.3f", f) + ";"
			}
		default:
			temp = temp + fmt.Sprintf("%v", v) + ";"
		}
	}

	b := []byte(temp)
	md5Ctx := md5.New()
	md5Ctx.Write(b)
	cipherStr := md5Ctx.Sum(nil)
	result := hex.EncodeToString(cipherStr)

	return strings.ToUpper(result)
}

/**
 * 验证当前'记录验证串'是否正确
 * @param key 加密密钥
 * @return boolean 正确返回true
 */
func (entity *VirtualEntity) ValidRecordKey(key string) bool {
	temp := entity.CreateRecordKey(key)
	return temp == entity.GetValue(TableRecordKey[0])
}

func (entity *VirtualEntity) Copy() *VirtualEntity {
	result := entity.New()

	result.JsonDbName = entity.JsonDbName           // 数据库名称别名,对应数据库全局配置名
	result.JsonName = entity.JsonName               // 所在数据库表对象名(首字母小写)
	result.DbName = entity.DbName                   // 所在数据库名称
	result.TableFullName = entity.TableFullName     // 所在数据库表表全名(数据库.表名)
	result.TableName = entity.TableName             // 所在数据库表表名称
	result.TableObj = entity.TableObj               // 所在数据库表对象名(首字母大写)
	result.KeyName = entity.KeyName                 // 表主键名称(首字母大写)
	result.KeyJson = entity.KeyJson                 // 表主键名称(json名称)
	result.KeyField = entity.KeyField               // 表主键字段
	result.KeyFields = entity.KeyFields             // 表主键字段集合(如果有多个主键,则全取,并以','分隔)
	result.KeyLen = entity.KeyLen                   // 主键长度
	result.AutoKey = entity.AutoKey                 // 是否自增主键
	result.HasPid = entity.HasPid                   // 是否存在pid
	result.HasPath = entity.HasPath                 // 是否存在path
	result.HasRecordKey = entity.HasRecordKey       // 是否存在recordKey
	result.HasMemo = entity.HasMemo                 // 是否存在memo
	result.HasCreator = entity.HasCreator           // 是否存在creator
	result.HasCreateDate = entity.HasCreateDate     // 是否存在createDate
	result.HasModifieder = entity.HasModifieder     // 是否存在modifieder
	result.HasModifiedDate = entity.HasModifiedDate // 是否存在modifiedDate
	result.HasState = entity.HasState               // 是否存在state
	result.HasRank = entity.HasRank                 // 是否存在rank
	result.HasEdition = entity.HasEdition           // 是否存在edition
	result.HasPassword = entity.HasPassword         // 是否存在password
	result.HasSign = entity.HasSign                 // 是否存在sign
	result.HasOnlyign = entity.HasOnlyign           // 是否存在onlyign
	result.HasDelSign = entity.HasDelSign           // 是否存在delSign
	result.HasAttached = entity.HasAttached         // 是否存在attached
	result.BigTextFields = entity.BigTextFields     // 大文本字段名称集合,';'分隔

	result.Fields = make(map[string]*FieldInfo, len(entity.Fields))
	for key, field := range entity.Fields {
		result.Fields[key] = field.Copy()
	}

	return result
}

/**
 * 参考结构体排除指定属性名称的字段
 * data 数据
 * removeNames 待移除的json名集合
 */
func (entity *VirtualEntity) RemoveData(data map[string]interface{}, removeNames ...string) map[string]interface{} {
	filter := make(map[string]string, len(removeNames))
	for _, v := range removeNames {
		filter[v] = ""
	}

	result := map[string]interface{}{}
	for k, v := range data {
		if _, ok := filter[k]; ok {
			continue //符合待排除属性名称
		}
		result[k] = v
	}

	return result
}

/**
 * 设置默认值
 * @param cover 是否覆盖
 */
func (entity *VirtualEntity) SetDefault(cover bool) *VirtualEntity {
	for _, field := range entity.Fields {
		if field.GoDefaultData == nil || field.GoDefaultData == "NULL" {
			continue
		}

		if !cover {
			continue
		}

		if field.GoDefaultData == "time.Now().Format(\"15:04:05\")" {
			field.Value = time.Now().Format("15:04:05")
			continue
		}

		if field.GoDefaultData == "time.Now().Format(\"2006-01-02 15:04:05\")" {
			field.Value = time.Now().Format("2006-01-02 15:04:05")
			continue
		}

		field.Value = field.GoDefaultData
	}

	return entity
}

/**
 * 按实体保留map中的数据
 * object 待检查对象
 * data 数据
 */
func (entity *VirtualEntity) HoldByEntity(data map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{}, len(data))
	for k, v := range data {
		if _, ok := entity.Fields[k]; ok {
			result[k] = v
			continue
		}

		if _, ok := entity.RelFields[k]; ok {
			result[k] = v
			continue
		}
	}

	return result
}

/**
 * 对对象中添加了FieldInfo字段的不为null的属性检查限制
 * data 数据
 * ignoreNames 待忽略的字段
 */
func (entity *VirtualEntity) ValidAttr(data map[string]interface{}, ignoreNames ...string) (int, error) {
	if data == nil {
		return 1001, createError("数据为nil")
	}

	if entity == nil {
		return 1002, createError("数据结构为nil")
	}

	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap[v] = struct{}{}
	}

	for _, fieldInfo := range entity.Fields {
		if _, ok := ignoreNamesMap[fieldInfo.Field]; ok { //忽略字段
			continue
		}

		if !fieldInfo.IsNull { //字段是否允许为空
			temp := data[fieldInfo.JsonName]
			if temp == nil { //数据如果为空
				return 1004, createError(fieldInfo.Comment, "[", fieldInfo.Name, "]不允许为空！")
			} else if fmt.Sprintf("%v", temp) == "" {
				return 1005, createError(fieldInfo.Comment, "[", fieldInfo.Name, "]不允许为空！")
			}
		}

		oldValue := fmt.Sprintf("%v", data[fieldInfo.JsonName])
		strType := fieldInfo.DbFileType

		if strType == "int" { // 此时oldValue的值为:"<int Value>"
			oldValue = fmt.Sprintf("%v", data[fieldInfo.JsonName])
		}

		iL := fieldInfo.MaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if !strings.Contains("/datetime/date/time/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
			return 1006, createError(fieldInfo.Comment, "[", fieldInfo.Name, "]长度超出，最大长度限制为:", iL)
		}
	}

	return 1999, nil
}

/**
 * 对'编辑'对象中添加了FieldInfo字段的不为null的属性检查限制
 * data 数据
 * ignoreNames 待忽略的字段
 */
func (entity *VirtualEntity) ValidAttrByEdit(data map[string]interface{}, ignoreNames ...string) (int, error) {
	if data == nil {
		return 1001, errors.New("数据为nil")
	}

	if entity == nil {
		return 1002, errors.New("数据结构为nil")
	}

	ignoreNamesMap := make(map[string]string, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap[v] = v
	}

	for _, fieldInfo := range entity.Fields {
		value, ok := data[fieldInfo.JsonName]
		if !ok {
			continue //此字段不参与更新则不进行检查
		}

		if _, ok = ignoreNamesMap[fieldInfo.Name]; ok {
			continue
		}

		oldValue := strings.TrimSpace(fmt.Sprintf("%v", value))
		strType := fieldInfo.DbFileType

		if strType == "int" { // 此时oldValue的值为:"<int Value>"
			oldValue = fmt.Sprintf("%v", value)
		}

		iL := fieldInfo.MaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if (!strings.Contains("/datetime/date/time/time.Time/decimal.Decimal", strType)) && (iL > 0) && (iL < utf8.RuneCountInString(oldValue)) {
			return 1003, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]长度超出，最大长度限制为:", iL)
		}

		if !fieldInfo.IsNull && (oldValue == "<nil>" || oldValue == "") {
			return 1004, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]不允许为空！")
		}

		if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
			str := fmt.Sprintf("%v", data[fieldInfo.JsonName])
			array := strings.Split(str, ".")

			if fieldInfo.IntLength < len(array[0]) {
				return 1005, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]整数超出，最大长度限制为:", fieldInfo.IntLength)
			}

			if (len(array) > 1) && (fieldInfo.DecimalLength < len(array[1])) {
				return 1006, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]小数超过，最大长度限制为:", fieldInfo.IntLength)
			}
		}

		if strings.Contains("/float64/float32/", strType) && (iL > 0) {
			str := fmt.Sprintf("%f", data[fieldInfo.JsonName])
			array := strings.Split(str, ".")

			if fieldInfo.IntLength < len(array[0]) {
				return 1005, createError(fieldInfo.Comment, "[", fieldInfo.Name, "]整数超出，最大长度限制为:", fieldInfo.IntLength)
			}

			if (len(array) > 1) && (fieldInfo.DecimalLength < len(array[1])) {
				return 1006, createError(fieldInfo.Comment, "[", fieldInfo.Name, "]小数超过，最大长度限制为:", fieldInfo.IntLength)
			}
		}
	}

	return 1999, nil
}

/**
 * 对'新增'对象中添加了FieldInfo字段的属性检查限制
 * ignoreNames 待忽略的字段
 */
func (entity *VirtualEntity) ValidAttrByAdd(ignoreNames ...string) (int, error) {
	if entity == nil {
		return 1001, createError("数据结构为nil")
	}

	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap[v] = struct{}{}
	}

	for _, fieldInfo := range entity.Fields {
		if fieldInfo.IsKey { //新增情况下不检查主键
			continue
		}

		if _, ok := ignoreNamesMap[fieldInfo.Name]; ok { //排除忽略字段
			continue
		}

		oldValue := fmt.Sprintf("%v", reflect.ValueOf(fieldInfo.Value))
		strType := fmt.Sprintf("%v", reflect.ValueOf(fieldInfo.Value).Type()) //类型

		if strType == "int" { // 此时oldValue的值为:"<int Value>"
			oldValue = fmt.Sprintf("%v", fieldInfo.Value)
		}

		iL := fieldInfo.MaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
			return 1002, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]长度超出，最大长度限制为:", iL)
		}

		if !fieldInfo.IsNull && ((oldValue == "<nil>") || (oldValue == "")) {
			return 1003, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]不允许为空！")
		}

		if strings.Contains("/datetime/date/time/time.Time/", strType) && !fieldInfo.IsNull && (oldValue == "" || oldValue == "0001-01-01 00:00:00 +0000 UTC" || oldValue == "<nil>") {
			return 1004, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]不允许为空！")
		}

		if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
			str := fmt.Sprintf("%v", fieldInfo.Value)
			array := strings.Split(str, ".")

			if fieldInfo.IntLength < len(array[0]) {
				return 1005, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]整数超出，最大长度限制为:", fieldInfo.IntLength)
			}

			if (len(array) > 1) && (fieldInfo.DecimalLength < len(array[1])) {
				return 1006, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]小数超过，最大长度限制为:", fieldInfo.IntLength)
			}
		}

		if strings.Contains("/float64/float32/", strType) && (iL > 0) {
			str := fmt.Sprintf("%v", fieldInfo.Value)
			array := strings.Split(str, ".")

			if fieldInfo.IntLength < len(array[0]) {
				return 1005, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]整数超出，最大长度限制为:", fieldInfo.IntLength)
			}

			if (len(array) > 1) && (fieldInfo.DecimalLength < len(array[1])) {
				return 1006, createError(fieldInfo.Comment, "[", fieldInfo.JsonName, "]小数超过，最大长度限制为:", fieldInfo.IntLength)
			}
		}
	}

	return 1999, nil
}
